package com.tcm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tcm.entity.Permission;
import com.tcm.entity.PermissionRole;
import com.tcm.entity.Role;
import com.tcm.entity.dto.param.PermissionRoleUpdateParam;
import com.tcm.entity.resp.PageR;
import com.tcm.entity.vo.PermissionListResult;
import com.tcm.entity.vo.RoleSelectResult;
import com.tcm.exception.DatabaseOperationException;
import com.tcm.mapper.PermissionMapper;
import com.tcm.mapper.PermissionRoleMapper;
import com.tcm.mapper.RoleUserMapper;
import com.tcm.service.PermissionService;
import com.tcm.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 权限管理业务类
 * @author Guqier
 * @version 1.0
 * @date 2023/7/2 19:58
 */
@Slf4j
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    private static final int ROLE_NORMAL_TYPE = 0;// 系统默认角色

    private static final int ROLE_DIY_TYPE = 2;// 用户自定义角色

    public static final int VISIT_PERMISSION_TYPE = 0;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionRoleMapper permissionRoleMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 分页获取角色列表
     * @param pageNum 当前页码
     * @param pageSize 页面大小
     * @return 角色列表分页信息
     */
    @Override
    public PageR<RoleSelectResult> getRoleListByPage(Integer pageNum, Integer pageSize){
        // 查询系统默认角色和自定义角色
        Page<Role> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Role::getType, ROLE_NORMAL_TYPE).or().eq(Role::getType, ROLE_DIY_TYPE);
        roleService.page(page, queryWrapper);
        // 构造结果集
        PageR<RoleSelectResult> pageR = new PageR<>();
        BeanUtils.copyProperties(page, pageR, "records");
        List<Role> records = page.getRecords();
        List<RoleSelectResult> results = new ArrayList<>();
        for (Role role : records) {
            RoleSelectResult roleSelectResult = new RoleSelectResult();
            BeanUtils.copyProperties(role, roleSelectResult);
            results.add(roleSelectResult);
        }
        pageR.setRecords(results);
        return pageR;
    }

    /**
     * 获取权限列表
     * @return 权限列表
     */
    @Override
    public List<PermissionListResult> getPermissionList(){
        LambdaQueryWrapper<Permission> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Permission::getType, VISIT_PERMISSION_TYPE);// 目前仅有访问权限
        List<Permission> list = this.list(queryWrapper);
        return list.stream().map((item) -> {
            PermissionListResult permissionListResult = new PermissionListResult();
            BeanUtils.copyProperties(item, permissionListResult);
            return permissionListResult;
        }).collect(Collectors.toList());
    }

    /**
     * 根据角色ID获取角色权限
     * @param roleId 角色ID
     * @return 角色权限列表
     */
    @Override
    public List<PermissionListResult> getPermissionByRoleId(Long roleId){
        List<PermissionListResult> results = new ArrayList<>();
        // 获取角色权限关系
        LambdaQueryWrapper<PermissionRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PermissionRole::getRoleId, roleId);
        List<PermissionRole> permissionRoles = permissionRoleMapper.selectList(queryWrapper);
        // 获取权限列表
        List<Permission> list = this.list();
        for (PermissionRole permissionRole : permissionRoles) {
            Optional<Permission> first = list.stream().filter(pr -> pr.getId().equals(permissionRole.getPermissionId())).findFirst();
            if (first.isPresent()) {
                Permission permission = first.get();
                PermissionListResult permissionListResult = new PermissionListResult();
                BeanUtils.copyProperties(permission, permissionListResult);
                results.add(permissionListResult);
            }
        }
        return results;
    }

    /**
     * 修改角色权限
     * @param param 修改角色权限参数封装对象
     * @param currUserId 当前登录用户ID
     * @return 修改结果，true为成功
     * @throws DatabaseOperationException 数据库操作异常
     */
    @Override
    public boolean modifyPermissionForRole(PermissionRoleUpdateParam param, Long currUserId) throws DatabaseOperationException{
        // 校验角色是否存在
        Role role = roleService.getById(param.getRoleId());
        if (role == null) {
            return false;
        }
        // 删除已有权限关系
        LambdaQueryWrapper<PermissionRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PermissionRole::getRoleId, role.getId());
        Integer count = permissionRoleMapper.selectCount(queryWrapper);
        int delete = permissionRoleMapper.delete(queryWrapper);
        if (count != delete){
            throw new DatabaseOperationException("数据库操作失败");
        }
        // 添加新权限
        List<Permission> list = this.list();
        int cnt = 0;
        for (Long permissionId : param.getPermissionIds()) {
            // 校验权限是否存在
            Optional<Permission> first = list.stream().filter(p -> p.getId().equals(permissionId)).findFirst();
            // 存在则保存角色权限关系
            if (first.isPresent()) {
                PermissionRole permissionRole = new PermissionRole();
                permissionRole.setRoleId(role.getId());
                permissionRole.setPermissionId(permissionId);
                permissionRole.setCreateUser(currUserId);
                permissionRole.setUpdateUser(currUserId);
                cnt += permissionRoleMapper.insert(permissionRole);
            }
        }
        if (cnt != param.getPermissionIds().size()) {
            throw new DatabaseOperationException("数据库操作失败");
        }
        return true;
    }

    /**
     * 添加自定义角色
     * @param roleKey 角色码
     * @param roleName 角色名称
     * @param des 角色描述
     * @param currUserId 当前登录用户ID
     * @return 添加结果，true为成功
     */
    @Override
    @Transactional
    public boolean addRole(String roleKey, String roleName, String des, Long currUserId){
        Role role = new Role();
        role.setRoleKey(roleKey);
        role.setRoleName(roleName);
        role.setDes(des);
        role.setType(ROLE_DIY_TYPE);// 添加的角色均为自定义角色
        role.setCreateUser(currUserId);
        role.setUpdateUser(currUserId);
        return roleService.save(role);
    }

    /**
     * 删除自定义角色
     * @param id 角色ID
     * @param currUserId 当前登录用户ID
     * @return 删除结果，true为成功
     * @throws Exception 异常
     */
    @Override
    @Transactional
    public boolean removeRole(Long id, Long currUserId) throws Exception {
        Role role = roleService.getById(id);
        if (role == null) {
            return false;
        }
        if (role.getType() != ROLE_DIY_TYPE){
            throw new Exception("不能删除系统预设角色");
        }
        role.setUpdateUser(currUserId);
        boolean b = roleService.updateById(role);
        boolean b1 = roleService.removeById(id);
        if (!b || !b1){
            throw new DatabaseOperationException("数据库操作异常");
        }
        // 删除角色权限关系
        LambdaQueryWrapper<PermissionRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PermissionRole::getRoleId, role.getId());
        Integer count = permissionRoleMapper.selectCount(queryWrapper);
        int delete = permissionRoleMapper.delete(queryWrapper);
        if (delete != count){
            throw new DatabaseOperationException("数据库操作异常");
        }
        return true;
    }

    /**
     * 通过用户ID获取权限码
     * @param userId 用户ID
     * @return 权限码列表
     */
    @Override
    public List<String> getPermissionKeyByUserId(Long userId){
        return permissionMapper.selectPermissionKeyByUserId(userId);
    }

}
